package cn.chiship.framework.upms.biz.system.service.impl;

import cn.chiship.framework.common.constants.SystemConfigConstants;
import cn.chiship.framework.common.pojo.vo.ConfigJson;
import cn.chiship.framework.common.pojo.vo.ExportDataResult;
import cn.chiship.framework.common.service.ExportService;
import cn.chiship.framework.common.service.GlobalCacheService;
import cn.chiship.framework.upms.biz.system.entity.UpmsSmsCode;
import cn.chiship.framework.upms.biz.system.entity.UpmsSmsCodeExample;
import cn.chiship.framework.upms.biz.system.mapper.UpmsSmsCodeMapper;
import cn.chiship.framework.upms.biz.system.service.UpmsSmsCodeService;
import cn.chiship.sdk.core.base.BaseResult;
import cn.chiship.sdk.core.base.ProgressResult;
import cn.chiship.sdk.core.base.constants.BaseConstants;
import cn.chiship.sdk.core.base.constants.RegularExpressionConstants;
import cn.chiship.sdk.core.enums.ProgressResultEnum;
import cn.chiship.sdk.core.exception.custom.BusinessException;
import cn.chiship.sdk.core.util.DateUtils;
import cn.chiship.sdk.core.util.RandomUtil;
import cn.chiship.sdk.framework.base.BaseServiceImpl;
import cn.chiship.sdk.framework.util.ExportUtil;
import cn.chiship.sdk.third.ali.AliDySmsUtil;
import cn.chiship.sdk.third.core.model.BaseConfigModel;
import com.google.common.collect.Maps;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.util.*;

/**
 * 验证码业务接口实现层
 * 2021/9/30
 *
 * @author lijian
 */
@Service
public class UpmsSmsCodeServiceImpl extends BaseServiceImpl<UpmsSmsCode, UpmsSmsCodeExample> implements UpmsSmsCodeService {

    private static final Logger LOGGER = LoggerFactory.getLogger(UpmsSmsCodeServiceImpl.class);

    @Resource
    UpmsSmsCodeMapper upmsSmsCodeMapper;
    @Resource
    ExportService exportService;

    @Resource
    GlobalCacheService globalCacheService;

    String fileName = "服务短信";
    String sheetName = "服务短信";
    String sheetTitle = "服务短信明细";

    @Override
    @Async
    public void asyncExportData(HttpServletResponse response, String taskId, Map<String, Object> paramMap) {
        try {
            processStatusHm.put(taskId, ProgressResult.out(ProgressResultEnum.PROGRESS_SEARCH_DATABASE_ENUM));
            Thread.sleep(1000);
            ExportDataResult exportDataResult = assemblyExportData(paramMap);
            processStatusHm.put(taskId, ProgressResult.out(ProgressResultEnum.PROGRESS_DOING_ENUM, "查询出" + exportDataResult.getTotal() + "条符合条件记录..."));
            Thread.sleep(1000);
            processStatusHm.put(taskId, ProgressResult.out(ProgressResultEnum.PROGRESS_FILE_ASSEMBLY_ENUM));

            //此行代码一定要放到最后执行，否则前段永远得不到下载流
            String exportType = paramMap.get("exportType").toString();
            byte[] bytes = ExportUtil.getInstance().getExportBytesByType(
                    exportType,
                    fileName,
                    fileName,
                    exportDataResult.getLabels(),
                    exportDataResult.getValues()
            );
            processStatusHm.put(taskId, ProgressResult.out(exportType, fileName, bytes));

        } catch (Exception e) {
            e.printStackTrace();
            processStatusHm.put(taskId, ProgressResult.out(ProgressResultEnum.PROGRESS_ERROR_ENUM, e.getLocalizedMessage()));
        }

    }


    @Override
    public void exportData(HttpServletResponse response, Map<String, Object> paramMap) throws Exception {
        ExportDataResult exportDataResult = assemblyExportData(paramMap);
        exportService.exportByType(response,
                paramMap.get("exportType").toString(),
                fileName,
                sheetName,
                sheetTitle,
                exportDataResult.getLabels(),
                exportDataResult.getValues()
        );
    }

    /**
     * 组装导出数据，此方法纯属为了同时支持同步导出与异步导出，减少代码书写
     *
     * @return
     */
    public ExportDataResult assemblyExportData(Map<String, Object> paramMap) {
        List<String> labels = new ArrayList<>();
        List<List<String>> valueList = new ArrayList<>();
        int total = 0;


        Map<String, Object> resultMap = Maps.newHashMapWithExpectedSize(7);
        labels.add("流水号");
        labels.add("设备号");
        labels.add("验证码");
        labels.add("状态");
        labels.add("类型");
        labels.add("有效期");
        UpmsSmsCodeExample upmsSmsCodeExample = new UpmsSmsCodeExample();
        List<UpmsSmsCode> upmsSmsCodes = upmsSmsCodeMapper.selectByExample(upmsSmsCodeExample);

        for (UpmsSmsCode upmsSmsCode : upmsSmsCodes) {
            List<String> values = new ArrayList<>();
            values.add(upmsSmsCode.getReferenceCode() + "");
            values.add(upmsSmsCode.getCodeDevice());
            values.add(upmsSmsCode.getCode());
            if (upmsSmsCode.getIsUsed() == BaseConstants.NO) {
                values.add("未使用");
            } else {
                values.add("已使用");
            }
            if (upmsSmsCode.getType() == BaseConstants.NO) {
                values.add("短信验证码");
            } else {
                values.add("邮箱验证码");
            }
            values.add(DateUtils.dateTime(upmsSmsCode.getGmtCreated()) + "~" + DateUtils.dateTime(upmsSmsCode.getExpiryTime()));
            valueList.add(values);
        }
        total = upmsSmsCodes.size();
        ExportDataResult exportDataResult = new ExportDataResult(
                labels,
                valueList,
                total
        );
        return exportDataResult;
    }

    @Override
    public BaseResult get(String codeDevice, Byte deviceType) {
        switch (deviceType) {
            case 0:
                if (!codeDevice.matches(RegularExpressionConstants.MOBILE)) {
                    return BaseResult.error("请输入正确的手机号码!");
                }
                break;
            case 1:
                if (!codeDevice.matches(RegularExpressionConstants.EMAIL)) {
                    return BaseResult.error("请输入正确的电子邮箱!");
                }
                break;
            default:
                return BaseResult.error("不支持的设备类型!");
        }
        try {
            /*
             * 短信厂家	smsType
             * 是否启用	isUseSms
             * 有效时间(分钟)	expiryTime
             * 模板编号	smsTemplate
             * 签名内容	signContent
             * 用户密钥	smsSecretKey
             * 用户编号	smsAccessKey
             */
            ConfigJson configJson = globalCacheService.getSystemConfigJson(Arrays.asList(
                    SystemConfigConstants.SMS_TYPE,
                    SystemConfigConstants.IS_USE_SMS,
                    SystemConfigConstants.EXPIRY_TIME,
                    SystemConfigConstants.SMS_TEMPLATE,
                    SystemConfigConstants.SIGN_CONTENT,
                    SystemConfigConstants.SMS_ACCESS_KEY,
                    SystemConfigConstants.SMS_SECRET_KEY
            ));
            int expiryTime = Integer.valueOf(configJson.getString(SystemConfigConstants.EXPIRY_TIME));

            UpmsSmsCodeExample upmsSmsCodeExample = new UpmsSmsCodeExample();
            UpmsSmsCodeExample.Criteria criteria = upmsSmsCodeExample.createCriteria();
            criteria.andCodeDeviceEqualTo(codeDevice);
            criteria.andIsUsedEqualTo(BaseConstants.NO);
            criteria.andTypeEqualTo(deviceType);
            criteria.andExpiryTimeGreaterThan(System.currentTimeMillis());
            upmsSmsCodeExample.setOrderByClause("id desc");
            List<UpmsSmsCode> smsCodes = upmsSmsCodeMapper.selectByExample(upmsSmsCodeExample);
            if (smsCodes.isEmpty()) {
                Map<String, Object> map = Maps.newHashMapWithExpectedSize(7);


                BaseResult baseResult = BaseResult.ok(null);
                String code = RandomUtil.number(6);
                //手机
                if (Byte.valueOf("0").equals(deviceType)) {
                    if (String.valueOf(BaseConstants.YES).equals(configJson.getString(SystemConfigConstants.IS_USE_SMS))) {
                        BaseConfigModel baseConfigModel = new BaseConfigModel(
                                configJson.getString(SystemConfigConstants.SMS_ACCESS_KEY),
                                configJson.getString(SystemConfigConstants.SMS_SECRET_KEY)
                        );
                        AliDySmsUtil aliDySmsUtil = AliDySmsUtil.getInstance().config(baseConfigModel);
                        Map<String, String> paramsMap = new HashMap<>(2);
                        paramsMap.put("code", code);
                        aliDySmsUtil.load(
                                configJson.getString(SystemConfigConstants.SIGN_CONTENT),
                                configJson.getString(SystemConfigConstants.SMS_TEMPLATE)
                        );
                        baseResult = aliDySmsUtil.sendSms(codeDevice, paramsMap);
                    } else {
                        map.put("code", code);
                    }
                }
                //邮箱
                if (Byte.valueOf("1").equals(deviceType)) {
                    map.put("code", code);
                }
                map.put("msg", "验证码已发送，有效期为" + expiryTime + "分钟，注意查收");
                map.put("expiryTime", expiryTime);

                if (baseResult.isSuccess()) {
                    UpmsSmsCode upmsSmsCode = new UpmsSmsCode();
                    upmsSmsCode.setId(RandomUtil.uuidLowerCase());
                    upmsSmsCode.setCode(code);
                    upmsSmsCode.setReferenceCode(System.currentTimeMillis());
                    upmsSmsCode.setExpiryTime(System.currentTimeMillis() + Integer.valueOf(configJson.getString(SystemConfigConstants.EXPIRY_TIME)) * 60 * 1000);
                    upmsSmsCode.setIsUsed(BaseConstants.NO);
                    upmsSmsCode.setCodeDevice(codeDevice);
                    upmsSmsCode.setIsDeleted(BaseConstants.NO);
                    upmsSmsCode.setGmtCreated(System.currentTimeMillis());
                    upmsSmsCode.setGmtModified(System.currentTimeMillis());
                    upmsSmsCode.setType(deviceType);
                    upmsSmsCodeMapper.insertSelective(upmsSmsCode);
                    // map.put("referenceCode", upmsSmsCode.getReferenceCode());

                    return BaseResult.ok(map);
                } else {
                    return baseResult;
                }
            } else {
                return BaseResult.error("您已获得验证码，有效期为" + expiryTime + "分钟");
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new BusinessException(e.getLocalizedMessage());
        }

    }

    @Override
    public BaseResult verification(String codeDevice, String code) {
        try {
            UpmsSmsCodeExample upmsSmsCodeExample = new UpmsSmsCodeExample();
            UpmsSmsCodeExample.Criteria criteria = upmsSmsCodeExample.createCriteria();
            criteria.andIsUsedEqualTo(BaseConstants.NO);
            criteria.andCodeDeviceEqualTo(codeDevice);
            criteria.andExpiryTimeGreaterThan(System.currentTimeMillis());
            upmsSmsCodeExample.setOrderByClause("gmt_modified desc");

            List<UpmsSmsCode> smsCodes = upmsSmsCodeMapper.selectByExample(upmsSmsCodeExample);
            if (!smsCodes.isEmpty()) {
                UpmsSmsCode smsCode = smsCodes.get(0);
                if (code.equals(smsCode.getCode())) {
                    smsCode.setIsUsed(BaseConstants.YES);
                    upmsSmsCodeMapper.updateByPrimaryKey(smsCode);
                    return BaseResult.ok();
                } else {
                    return BaseResult.error("验证码错误,请重新输入");
                }
            } else {
                return BaseResult.error("验证码已失效，请重新获取");
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new BusinessException(e.getLocalizedMessage());
        }
    }

    @Override
    public BaseResult check(String codeDevice, String code) {
        try {
            UpmsSmsCodeExample upmsSmsCodeExample = new UpmsSmsCodeExample();
            upmsSmsCodeExample.createCriteria()
                    .andIsUsedEqualTo(BaseConstants.NO)
                    .andCodeEqualTo(code)
                    .andCodeDeviceEqualTo(codeDevice)
                    .andExpiryTimeGreaterThan(System.currentTimeMillis());
            upmsSmsCodeExample.setOrderByClause("gmt_modified desc");
            List<UpmsSmsCode> smsCodes = upmsSmsCodeMapper.selectByExample(upmsSmsCodeExample);
            if (!smsCodes.isEmpty()) {
                return BaseResult.ok();
            } else {
                return BaseResult.error("验证码错误,请重新输入");
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new BusinessException(e.getLocalizedMessage());
        }

    }


}
